#include <iostream>
#include <string>
#include <memory>

class Fruit
{
public:
    Fruit() {}
    virtual void show() = 0;
};

class Apple : public Fruit
{
public:
    Apple() {}
    void show()
    {
        std::cout << "I am a apple!" << std::endl;
    }
};

class Pear : public Fruit
{
public:
    Pear() {}
    void show()
    {
        std::cout << "I am a pear!" << std::endl;
    }
};

class Animal
{
public:
    virtual void voice() = 0;
};

class Lamp : public Animal
{
public:
    void voice()
    {
        std::cout << "咩咩咩\n";
    }
};

class Dog : public Animal
{
public:
    void voice()
    {
        std::cout << "汪汪汪\n";
    }
};
/*简单工厂模式*/
// class FruitFactory
// {
// public:
//     static std::shared_ptr<Fruit> CreateFruit(std::string goods)
//     {
//         if(goods == "apple")
//         {
//             return std::make_shared<Apple>();
//         }
//         else
//         {
//             return std::make_shared<Pear>();
//         }
//     }
// };
/*工厂方法模式*/
// class Factory
// {
// public:
//     virtual std::shared_ptr<Fruit> Create() = 0;
// };

// class AppleFactory : public Factory
// {
// public:
//     std::shared_ptr<Fruit> Create()
//     {
//         return std::make_shared<Apple>();
//     }
// };

// class PearFactory : public Factory
// {
// public:
//     std::shared_ptr<Fruit> Create()
//     {
//         return std::make_shared<Pear>();
//     }
// };
/*抽象工厂模式*/
class SuperFactory
{
public:
    virtual std::shared_ptr<Animal> GetAnimal(const std::string &goods) = 0;
    virtual std::shared_ptr<Fruit> GetFruit(const std::string &goods) = 0;
};

class FruitFactory : public SuperFactory
{
public:
    std::shared_ptr<Animal> GetAnimal(const std::string &goods)
    {
        return std::shared_ptr<Animal>();
    }

    std::shared_ptr<Fruit> GetFruit(const std::string &goods)
    {
        if (goods == "apple")
        {
            return std::make_shared<Apple>();
        }
        else
        {
            return std::make_shared<Pear>();
        }
    }
};

class AnimalFactory : public SuperFactory
{
public:
    std::shared_ptr<Animal> GetAnimal(const std::string &goods)
    {
        if (goods == "dog")
        {
            return std::make_shared<Dog>();
        }
        else
        {
            return std::make_shared<Lamp>();
        }
    }

    std::shared_ptr<Fruit> GetFruit(const std::string &goods)
    {
        return nullptr;
    }
};

class FactoryProducer
{
public:
    static std::shared_ptr<SuperFactory> Create(const std::string &factory)
    {
        if (factory == "Animal")
        {
            return std::make_shared<AnimalFactory>();
        }
        else
        {
            return std::make_shared<FruitFactory>();
        }
    }
};

int main()
{
    // std::shared_ptr<Fruit> fruit = FruitFactory::CreateFruit("apple");
    // fruit->show();
    // fruit = FruitFactory::CreateFruit("pear");
    // fruit->show();

    // std::shared_ptr<Factory> factory(new AppleFactory);
    // std::shared_ptr<Fruit> fruit = factory->Create();
    // fruit->show();
    // factory.reset(new PearFactory);
    // fruit = factory->Create();
    // fruit->show();

    std::shared_ptr<SuperFactory> factory = FactoryProducer::Create("Animal");
    std::shared_ptr<Animal> animal = factory->GetAnimal("dog");
    animal->voice();
    animal = factory->GetAnimal("lamp");
    animal->voice();

    factory = FactoryProducer::Create("Fruit");
    std::shared_ptr<Fruit> fruit = factory->GetFruit("apple");
    fruit->show();
    fruit = factory->GetFruit("pear");
    fruit->show();

    return 0;
}